﻿using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace Model
{
    
    public abstract  class NetworkComponent : Component
    {
        private TService service;

        public AppType AppType;

        public ProtobufPacker Packer { get; set; }

        public AMessageDispatcher MessageDispatcher { get; set; }

        private readonly Dictionary<long, Session> sessions = new Dictionary<long, Session>();

        public void Awake(IPEndPoint iPEndPoint)
        {
            service = new TService(iPEndPoint);
            this.StartAccept();
        }

        private async void StartAccept()
        {
            while (true)
            {
                if (this.Id == 0) return;

                await this.Accept();
            }
        }

        public virtual async Task<Session> Accept()
        {
            TChannel channel = await service.AcceptChannel();
            Session session = EntityFactory.Create<Session, TChannel, NetworkComponent>(channel, this);
            channel.ErrorCallback += (c, e) => { this.Remove(session.Id); };
            this.sessions.Add(session.Id,session);
            return session;
        }

        /// <summary>
        /// 创建一个新Session
        /// </summary>
        /// <param name="iPEndPoint"></param>
        /// <returns></returns>
        public  virtual Session Create(IPEndPoint iPEndPoint)
        {
            TChannel channel = this.service.ConnectChannel(iPEndPoint);
            Session session = EntityFactory.Create<Session, TChannel, NetworkComponent>(channel, this);
            channel.ErrorCallback += (c, e) => { this.Remove(session.Id); };
            this.sessions.Add(session.Id, session);
            return session;
        }

        /// <summary>
        /// 根据ID获取Session
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public Session Get(long id)
        {
            this.sessions.TryGetValue(id, out Session session);
            return session;
        }



        /// <summary>
        /// 移除Session
        /// </summary>
        /// <param name="id"></param>
        public virtual void Remove(long id)
        {
            if (!this.sessions.TryGetValue(id, out Session session))
                return;

            this.sessions.Remove(id);
            session.Dispose();
        }
    }
}
